package com.xishu.service;

import com.xishu.dao.DaoUtil;
import com.xishu.entity.AbstractEntity;
import com.xishu.entity.config.BackConfig;
import com.xishu.entity.hardware.Printer;
import com.xishu.entity.hardware.PrinterLabel;
import com.xishu.entity.shop.*;
import com.xishu.entity.takeout.TakeOutConfig;
import com.xishu.response.VerifyUtil;
import com.xishu.util.ClassUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.List;

public class BackConfigService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(BackConfigService.class);
    private static CommonService commonService = CommonService.getInstance();
    private static BackConfigService instance = new BackConfigService();

    private BackConfigService() {
    }

    public static BackConfigService getInstance() {
        return instance;
    }

    /**
     * 备份
     *
     * @param backConfig
     */
    public void back(BackConfig backConfig) throws Exception {
        VerifyUtil.verify(() -> backConfig != null);
        VerifyUtil.verify(() -> backConfig.getId() != null);
        VerifyUtil.verify(() -> backConfig.getShopId() != null);
        //查询出当前的分店，做备份
        Shop shop = ShopService.getInstance().findShopById(backConfig.getShopId());
        backEntity(shop, backConfig.getId());

        //备份打印标签
        backEntity(shop.getId(), backConfig.getId(), PrinterLabel.class);

        //备份场景
        backEntity(shop.getId(), backConfig.getId(), Scene.class);

        //运营模式
        backEntity(shop.getId(), backConfig.getId(), RunModel.class);

        //餐桌管理
        backEntity(shop.getId(), backConfig.getId(), FoodTable.class);

        //餐桌配置设定
        backEntity(shop.getId(), backConfig.getId(), FoodTableConfig.class);

        //打印机
        backEntity(shop.getId(), backConfig.getId(), Printer.class);

        //品类
        backEntity(shop.getId(), backConfig.getId(), Catalog.class);

        //菜品
        backEntity(shop.getId(), backConfig.getId(), Item.class);

        //优惠卷
        //backEntity(shop.getId(), backConfig.getId(), DiscountTicket.class);

        //排队配置
        backEntity(shop.getId(), backConfig.getId(), LineUpConfig.class);

        //外卖平台配置
        backEntity(shop.getId(), backConfig.getId(), TakeOutConfig.class);

        //外卖设定配置
        backEntity(shop.getId(), backConfig.getId(), TakeOutSetting.class);

        //支付方式
        backEntity(shop.getId(), backConfig.getId(), PayType.class);

        //Shop(包含第三方支付和二维码等多种配置)
        backEntity(shop.getId(), backConfig.getId(), Shop.class);


    }

    /**
     * 备份对应的一张表,通过shopId去查找
     *
     * @param
     * @param tClass
     * @param <T>
     */
    public <T extends AbstractEntity> void backEntity(Long shopId, Long version, Class<T> tClass) throws Exception {
        T newInstance = tClass.newInstance();
        Field shopIdField = ClassUtil.getInstance().getField(tClass, "shopId");
        newInstance.setEntity(true);

        VerifyUtil.verify(() -> shopIdField != null);
        shopIdField.set(newInstance, shopId);
        CommonService commonService = CommonService.getInstance();
        List<T> backupIngList = commonService.searchAll(newInstance);

        for (T t : backupIngList) {
            backEntity(t, version);
        }
    }

    /**
     * 备份一个实体，每备份一次，版本号均不相同
     *
     * @param <T>
     */
    public <T extends AbstractEntity> void backEntity(T t, Long version) throws Exception {
        AbstractEntity entity = t.getClass().newInstance();
        BeanUtils.copyProperties(t, entity);
        entity.setId(null);

        //设置版本号,设置备份的对象的ID
        entity.setVersion(version);
        entity.setEntity(false);
        entity.setBackupTargetId(t.getId());
        entity.setFlagDelete(false);

        commonService.directSave(entity);
    }

    /**
     * 还原
     *
     * @param backConfig
     */
    public void restoreShop(BackConfig backConfig) throws Exception {
        VerifyUtil.verify(() -> backConfig != null);
        VerifyUtil.verify(() -> backConfig.getId() != null);
        VerifyUtil.verify(() -> backConfig.getShopId() != null);
        restoreShop(backConfig.getShopId(), backConfig.getId());

        //恢复标签
        restoreEntity(backConfig.getShopId(), backConfig.getId(), PrinterLabel.class);

        //恢复场景
        restoreEntity(backConfig.getShopId(), backConfig.getId(), Scene.class);

        //运营模式
        restoreEntity(backConfig.getShopId(), backConfig.getId(), RunModel.class);

        //餐桌管理
        restoreEntity(backConfig.getShopId(), backConfig.getId(), FoodTable.class);

        //餐桌配置设定
        restoreEntity(backConfig.getShopId(), backConfig.getId(), FoodTableConfig.class);

        //打印机
        restoreEntity(backConfig.getShopId(), backConfig.getId(), Printer.class);

        //品类
        restoreEntity(backConfig.getShopId(), backConfig.getId(), Catalog.class);

        //菜品
        restoreEntity(backConfig.getShopId(), backConfig.getId(), Item.class);

        //优惠卷
        //restoreEntity(backConfig.getShopId(), backConfig.getId(), DiscountTicket.class);

        //排队配置
        restoreEntity(backConfig.getShopId(), backConfig.getId(), LineUpConfig.class);

        //外卖平台配置
        restoreEntity(backConfig.getShopId(), backConfig.getId(), TakeOutConfig.class);

        //外卖设定配置
        restoreEntity(backConfig.getShopId(),backConfig.getId(),TakeOutSetting.class);

        //支付方式
        restoreEntity(backConfig.getShopId(), backConfig.getId(), PayType.class);

        //Shop
        restoreEntity(backConfig.getShopId(), backConfig.getId(), Shop.class);


    }

    /**
     * 用对应的版本号恢复一个实体
     *
     * @param <T>
     */
    public <T extends AbstractEntity> void restoreShop(Long shopId, Long version) throws Exception {
        Shop versionShop = new Shop();
        versionShop.setVersion(version);
        versionShop.setContainBackupEntity(true);
        CommonService commonService = CommonService.getInstance();
        List<AbstractEntity> entityList = commonService.searchAll(versionShop);

        logger.info("entity list size is {}", entityList.size());

        //只能有一个
        //VerifyUtil.verify(() -> isNotEmpty(entityList) && entityList.size() == 1);
        // VerifyUtil.verify(() -> isNotEmpty(entityList));
        //如果是一个空备份，直接结束
        if (isEmpty(entityList)){
            return;
        }
        AbstractEntity versionEntity = entityList.get(0);

        //查找当前的对象
        Shop currentShop = new Shop();
        currentShop.setEntity(true);
        currentShop.setId(shopId);
        List<AbstractEntity> abstractEntityList = commonService.searchAll(currentShop);
        VerifyUtil.verify(() -> isNotEmpty(abstractEntityList) && abstractEntityList.size() == 1);
        AbstractEntity currentEntity = abstractEntityList.get(0);


        BeanUtils.copyProperties(versionEntity, currentEntity, "version", "backupTargetId", "entity", "id");
        commonService.save(currentEntity);

    }

    /**
     * 恢复一个实体
     *
     * @param version
     * @param tclass
     * @param shopId
     * @param <T>
     */
    public <T extends AbstractEntity> void restoreEntity(Long shopId, Long version, Class<T> tclass) throws Exception {
        CommonService commonService = CommonService.getInstance();
        //把当前相关的对象设置成标记删除
        T currentListSearch = tclass.newInstance();
        Field shopIdField = ClassUtil.getInstance().getField(tclass, "shopId");
        currentListSearch.setEntity(true);
        shopIdField.set(currentListSearch, shopId);

        //先把当前的设置都改成备份
        for (T currentObject : commonService.searchAll(currentListSearch)) {
            currentObject.setEntity(false);
            commonService.save(currentObject);
        }

        T newInstance = tclass.newInstance();
        newInstance.setVersion(version);
        newInstance.setContainBackupEntity(true);
        //先通过ID找到该对象，如果没有找到该对象，则对应的数据不恢复
        List<T> backUpEntityList = commonService.searchAll(newInstance);

        //遍历这个版本的所有对象
        for (T backUpEntity : backUpEntityList) {
            //找到对应的实体
            if (backUpEntity.getBackupTargetId() == null) {
                logger.error("can not find the targetId in version {} , and class is {}", version, tclass.getName());
                continue;
            }

            DaoUtil daoUtil = DaoUtil.getInstance();
            T targetEntity = daoUtil.findById(backUpEntity.backupTargetId, tclass);
            if (targetEntity == null) {
                logger.error("can not find the target entity {} in db, class is {]", version, tclass.getName());
                continue;
            }

            //找到了该对象，则赋值操作
            BeanUtils.copyProperties(backUpEntity, targetEntity, "version", "backupTargetId", "entity", "id");
            targetEntity.setEntity(true);
            commonService.save(targetEntity);
        }

    }
}
